interface Item {
    name(): string;
    packing(): Packing;
    price(): number;
}

interface Packing {
    pack(): string;
}

class Wrapper implements Packing {
    public pack(): string {
        return 'Wrapper';
    }
}

class Bottle implements Packing {
    public pack(): string {
        return 'Bottle';
    }
}

abstract class Burger implements Item {
    public packing(): Packing {
        return new Wrapper();
    }
    public abstract price(): number;
    public abstract name(): string;
}

abstract class ColdDrink implements Item {
    public packing(): Packing {
        return new Bottle();
    }
    public abstract price(): number;
    public abstract name(): string;
}

class VegBurger extends Burger {
    public override price(): number {
        return 25.0;
    }
    public override name(): string {
        return 'Veg Burger';
    }
}

class ChickenBurger extends Burger {
    public override price(): number {
        return 50.5;
    }
    public override name(): string {
        return 'Chicken Burger';
    }
}

class Coke extends ColdDrink {
    public override price(): number {
        return 30.0;
    }
    public override name(): string {
        return 'Coke';
    }
}

class Pepsi extends ColdDrink {
    public override price(): number {
        return 35.0;
    }
    public override name(): string {
        return 'Pepsi';
    }
}

class Meal {
    private items: Array<Item> = new Array<Item>();
    public name: string;
    constructor(name: string) {
        this.name = name;
    }
    public addItem(item: Item): void {
        this.items.push(item);
    }
    public getCost(): number {
        let cost: number = 0;
        for (const item of this.items) {
            cost += item.price();
        }
        return cost;
    }
    public showInfo(): void {
        console.log('Meal: ' + this.name)
        for (const item of this.items) {
            console.log('  Item: ' + item.name());
            console.log('  Packing: ' + item.packing().pack());
            console.log('  Price: ' + item.price());
        }
    }
}

class MealBuilder {
    public prepareVegMeal(): Meal {
        const meal: Meal = new Meal('Veg Meal');
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }
    public prepareNonVegMeal(): Meal {
        const meal: Meal = new Meal('Non-Veg Meal');
        meal.addItem(new ChickenBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}

function main() {
    const mealBuilder: MealBuilder = new MealBuilder();

    const vegMeal: Meal = mealBuilder.prepareVegMeal();
    vegMeal.showInfo();
    console.log('Total cost: ' + vegMeal.getCost());

    const nonVegMeal: Meal = mealBuilder.prepareNonVegMeal();
    nonVegMeal.showInfo();
    console.log('Total cost: ' + nonVegMeal.getCost());
}

main();
